package com.christina.engine.strategy.impl;

import com.christina.engine.strategy.RoutingStrategy;
import com.christina.engine.strategy.model.RoutingContext;
import com.christina.engine.strategy.model.RoutingDecision;
import com.christina.engine.intent.model.Intent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;

/**
 * 基于意图的路由策略
 * 根据识别的意图类型进行服务路由
 * 
 * @author Christina
 */
@Slf4j
@Component
public class IntentBasedRoutingStrategy implements RoutingStrategy {
    
    private static final String STRATEGY_NAME = "IntentBasedRouting";
    private static final int PRIORITY = 100; // 高优先级
    
    // 意图到服务的映射配置
    private final Map<String, ServiceMapping> intentServiceMappings = new HashMap<>();
    
    public IntentBasedRoutingStrategy() {
        initializeIntentMappings();
    }
    
    @Override
    public String getStrategyName() {
        return STRATEGY_NAME;
    }
    
    /**
     * 初始化意图映射配置
     */
    private void initializeIntentMappings() {
        // 出行相关意图
        intentServiceMappings.put("travel_planning", new ServiceMapping("TravelDomainService", "planTravel", 0.9));
        intentServiceMappings.put("travel_booking", new ServiceMapping("TravelDomainService", "bookTravel", 0.95));
        intentServiceMappings.put("travel_query", new ServiceMapping("TravelDomainService", "queryTravel", 0.85));
        intentServiceMappings.put("hotel_booking", new ServiceMapping("TravelDomainService", "bookHotel", 0.9));
        intentServiceMappings.put("flight_booking", new ServiceMapping("TravelDomainService", "bookFlight", 0.9));
        
        // 聊天相关意图
        intentServiceMappings.put("general_chat", new ServiceMapping("ChatDomainService", "processChat", 0.8));
        intentServiceMappings.put("question_answer", new ServiceMapping("ChatDomainService", "answerQuestion", 0.85));
        intentServiceMappings.put("information_query", new ServiceMapping("ChatDomainService", "queryInformation", 0.8));
        intentServiceMappings.put("translation", new ServiceMapping("ChatDomainService", "translate", 0.9));
        intentServiceMappings.put("summarization", new ServiceMapping("ChatDomainService", "summarize", 0.9));
        
        // 用户相关意图
        intentServiceMappings.put("user_profile", new ServiceMapping("UserDomainService", "manageProfile", 0.95));
        intentServiceMappings.put("user_settings", new ServiceMapping("UserDomainService", "updateSettings", 0.95));
        intentServiceMappings.put("user_preferences", new ServiceMapping("UserDomainService", "managePreferences", 0.9));
        intentServiceMappings.put("authentication", new ServiceMapping("UserDomainService", "authenticate", 0.95));
        
        log.info("Initialized {} intent-to-service mappings", intentServiceMappings.size());
    }
    
    @Override
    public RoutingDecision makeDecision(RoutingContext context) {
        Intent intent = context.getIntent();
        if (intent == null) {
            return RoutingDecision.failure("No intent available for routing", STRATEGY_NAME);
        }
        
        Intent.IntentType intentType = intent.getType();
        if (intentType == null) {
            return RoutingDecision.failure("Intent type is null", STRATEGY_NAME);
        }
        
        String intentTypeName = intentType.name().toLowerCase();
        
        // 查找精确匹配的映射
        ServiceMapping mapping = intentServiceMappings.get(intentTypeName);
        if (mapping != null) {
            return createDecisionFromMapping(mapping, intent, "Exact intent match");
        }
        
        // 尝试模糊匹配
        mapping = findFuzzyMatch(intentTypeName);
        if (mapping != null) {
            return createDecisionFromMapping(mapping, intent, "Fuzzy intent match");
        }
        
        // 尝试基于意图类别的匹配
        mapping = findCategoryMatch(intentTypeName);
        if (mapping != null) {
            return createDecisionFromMapping(mapping, intent, "Category-based match");
        }
        
        return RoutingDecision.failure("No matching service found for intent: " + intentTypeName, STRATEGY_NAME);
    }
    
    /**
     * 根据映射创建路由决策
     * 
     * @param mapping 服务映射
     * @param intent 意图
     * @param reason 决策原因
     * @return 路由决策
     */
    private RoutingDecision createDecisionFromMapping(ServiceMapping mapping, Intent intent, String reason) {
        if (mapping == null) {
            return RoutingDecision.failure("Service mapping is null", STRATEGY_NAME);
        }
        
        double finalConfidence = calculateFinalConfidence(mapping.confidence, intent);
        
        RoutingDecision.RoutingDecisionBuilder builder = RoutingDecision.builder()
                .targetService(mapping.serviceName)
                .serviceMethod(mapping.methodName)
                .confidence(finalConfidence)
                .reason(reason + " for intent: " + intent.getType().name())
                .strategyName(STRATEGY_NAME);
        
        // 如果置信度较低，添加回退策略
        if (finalConfidence < 0.7) {
            builder.needsFallback(true)
                   .fallbackService("ChatDomainService");
        }
        
        return builder.build();
    }
    
    /**
     * 计算最终置信度
     * 
     * @param mappingConfidence 映射置信度
     * @param intent 意图
     * @return 最终置信度
     */
    private double calculateFinalConfidence(double mappingConfidence, Intent intent) {
        double intentConfidence = intent.getConfidence() != 0.0 ? intent.getConfidence() : 0.5;
        
        // 综合考虑映射置信度和意图识别置信度
        return mappingConfidence * 0.7 + intentConfidence * 0.3;
    }
    
    /**
     * 查找模糊匹配的映射
     * 
     * @param intentType 意图类型
     * @return 服务映射，如果没有找到返回null
     */
    private ServiceMapping findFuzzyMatch(String intentType) {
        if (intentType == null) {
            return null;
        }
        
        String lowerIntentType = intentType.toLowerCase();
        
        // 检查是否包含关键词
        for (Map.Entry<String, ServiceMapping> entry : intentServiceMappings.entrySet()) {
            String mappingKey = entry.getKey();
            
            // 检查意图类型是否包含映射键的关键词
            if (lowerIntentType.contains(mappingKey.split("_")[0])) {
                ServiceMapping mapping = entry.getValue();
                // 降低置信度，因为是模糊匹配
                return new ServiceMapping(mapping.serviceName, mapping.methodName, mapping.confidence * 0.8);
            }
        }
        
        return null;
    }
    
    /**
     * 查找基于类别的匹配
     * 
     * @param intentType 意图类型
     * @return 服务映射，如果没有找到返回null
     */
    private ServiceMapping findCategoryMatch(String intentType) {
        if (intentType == null) {
            return null;
        }
        
        String lowerIntentType = intentType.toLowerCase();
        
        // 出行类别
        if (lowerIntentType.contains("travel") || lowerIntentType.contains("trip") || 
            lowerIntentType.contains("booking") || lowerIntentType.contains("hotel") ||
            lowerIntentType.contains("flight") || lowerIntentType.contains("transport")) {
            return new ServiceMapping("TravelDomainService", "processRequest", 0.6);
        }
        
        // 用户类别
        if (lowerIntentType.contains("user") || lowerIntentType.contains("profile") ||
            lowerIntentType.contains("setting") || lowerIntentType.contains("preference") ||
            lowerIntentType.contains("account") || lowerIntentType.contains("auth")) {
            return new ServiceMapping("UserDomainService", "processRequest", 0.6);
        }
        
        // 默认聊天类别
        return new ServiceMapping("ChatDomainService", "processChat", 0.5);
    }
    
    @Override
    public int getPriority() {
        return PRIORITY;
    }
    
    @Override
    public boolean isApplicable(RoutingContext context) {
        return context != null && context.getIntent() != null && 
               context.getIntent().getType() != null;
    }
    
    @Override
    public double getConfidence(RoutingContext context) {
        if (!isApplicable(context)) {
            return 0.0;
        }
        
        Intent intent = context.getIntent();
        String intentTypeName = intent.getType().name().toLowerCase();
        
        // 检查是否有精确匹配
        if (intentServiceMappings.containsKey(intentTypeName)) {
            return 0.9;
        }
        
        // 检查模糊匹配
        if (findFuzzyMatch(intentTypeName) != null) {
            return 0.7;
        }
        
        // 检查类别匹配
        if (findCategoryMatch(intentTypeName) != null) {
            return 0.5;
        }
        
        return 0.1;
    }
    
    /**
     * 添加新的意图映射
     * 
     * @param intentType 意图类型
     * @param serviceName 服务名称
     * @param methodName 方法名称
     * @param confidence 置信度
     */
    public void addIntentMapping(String intentType, String serviceName, String methodName, double confidence) {
        if (intentType != null && serviceName != null) {
            intentServiceMappings.put(intentType.toLowerCase(), 
                    new ServiceMapping(serviceName, methodName, confidence));
            log.info("Added intent mapping: {} -> {}.{} (confidence: {})", 
                    intentType, serviceName, methodName, confidence);
        }
    }
    
    /**
     * 移除意图映射
     * 
     * @param intentType 意图类型
     */
    public void removeIntentMapping(String intentType) {
        if (intentType != null) {
            ServiceMapping removed = intentServiceMappings.remove(intentType.toLowerCase());
            if (removed != null) {
                log.info("Removed intent mapping for: {}", intentType);
            }
        }
    }
    
    /**
     * 获取所有意图映射
     * 
     * @return 意图映射
     */
    public Map<String, ServiceMapping> getAllMappings() {
        return new HashMap<>(intentServiceMappings);
    }
    
    /**
     * 服务映射内部类
     */
    public static class ServiceMapping {
        public final String serviceName;
        public final String methodName;
        public final double confidence;
        
        public ServiceMapping(String serviceName, String methodName, double confidence) {
            this.serviceName = serviceName;
            this.methodName = methodName;
            this.confidence = confidence;
        }
        
        @Override
        public String toString() {
            return String.format("ServiceMapping{service='%s', method='%s', confidence=%.2f}", 
                    serviceName, methodName, confidence);
        }
    }
}